package com.th.supcom.pds.impl.service.internal.phamapply.command;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.chain.Command;
import org.apache.commons.chain.Context;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.th.supcom.pds.domain.pojo.InpPhamApplyDetailSummary;
import com.th.supcom.pds.domain.pojo.InpPhamDispenseDetail;
import com.th.supcom.pds.domain.vo.InpPhamApplyDetailVO;
import com.th.supcom.pds.domain.vo.InpPhamDispenseDetailVO;
import com.th.supcom.pds.impl.common.enums.InpDispenseIndicator;
import com.th.supcom.pds.impl.service.internal.phamapply.PhamApplyConvertUtils;
import com.th.supcom.pds.impl.service.internal.phamapply.PhamDispenseConvertUtils;

/**
 * 更新可冲抵摆药请领明细及对应执行明细
 * 
 * @author leaqua@qq.com
 */
public class ApplyDetailOffsetPhamOp extends AbstractPhamApplyManagerBean implements Command
{

    @Override
    public boolean execute (Context arg0) throws Exception
    {
        PhamDispenseContext context = (PhamDispenseContext) arg0;
        // 药品属性以及该药房需摆药单个药品数量汇总
        List <InpPhamApplyDetailSummary> phamInfoList = context.getPhamInfoList ();
        // 按照药品标准码分组的请领执行明细
        Map <String, List <InpPhamDispenseDetailVO>> dispenseDetailMap = context.getDispenseDetailByPhamStdCode ();
        // 即将冲抵的摆药请领明细对应的执行明细
        List <InpPhamDispenseDetail> offsetedDispenseDetail = new ArrayList <InpPhamDispenseDetail> ();
        // 可冲抵明细汇总
        List <InpPhamApplyDetailVO> offsetApplyDetailSummary = this.getInpPhamApplyDetailBasicService ().findOffsetPhamListSummary (phamInfoList);
        Map <String, InpPhamApplyDetailVO> offsetApplyDetailSummaryByCode = PhamApplyConvertUtils.convertSummaryListToMapByPhamStdCode (offsetApplyDetailSummary);
        // 即将冲抵的明细药品汇总明细
        List <InpPhamApplyDetailVO> aboutToOffsetApplyDetails = new ArrayList <InpPhamApplyDetailVO> ();
        Set <Entry <String, InpPhamApplyDetailVO>> set = offsetApplyDetailSummaryByCode.entrySet ();
        for (Entry <String, InpPhamApplyDetailVO> entry : set)
        {
            // 执行明细
            // TODO
            List <InpPhamDispenseDetailVO> dipenseDetail = dispenseDetailMap.get (entry.getValue ().getPhamStdCode ());
            InpPhamApplyDetailVO offsetApplyDetailSummaryDetail = offsetApplyDetailSummaryByCode.get (entry.getValue ().getPhamStdCode ());
            // 如果该种药品没有可冲抵的明细
            if (CollectionUtils.isEmpty (dipenseDetail))
            {
                continue;
            }
            // 如果可冲抵药品的发药药房和本次请领该药品的发药药房不同，跳过
            if (!entry.getValue ().getExecDispensary ().equals (dipenseDetail.get (0).getPerformDispensary ()))
            {
                continue;
            }
            InpPhamApplyDetailVO aboutToOffsetDetailVO = new InpPhamApplyDetailVO ();
            aboutToOffsetDetailVO.setPhamStdCode (entry.getValue ().getPhamStdCode ());
            aboutToOffsetDetailVO.setNurseUnit (entry.getValue ().getNurseUnit ());
            Integer sum = 0;
            for (InpPhamDispenseDetailVO inpPhamDispenseDetailVO : dipenseDetail)
            {
                sum += inpPhamDispenseDetailVO.getApplyAmount ();
                if (sum > offsetApplyDetailSummaryDetail.getOffsetSum ())
                {
                    sum = offsetApplyDetailSummaryDetail.getOffsetSum ();
                    break;
                }

            }
            aboutToOffsetDetailVO.setOffsetSum (sum);
            aboutToOffsetApplyDetails.add (aboutToOffsetDetailVO);

        }
        List <InpPhamDispenseDetailVO> dispenseList = PhamDispenseConvertUtils.convertMapToListByPhamStdCode (dispenseDetailMap);
        context.setOffsetedDispenseDetail (offsetedDispenseDetail);
        context.setInpPhamDispenseDetailVOList (dispenseList);
        context.setOffsetedApplyDetail (aboutToOffsetApplyDetails);
        return false;
    }

    /**
     * 根据冲抵数量来更新摆药执行明细中的药品数量
     * 
     * @param dispenseDetailList 执行明细
     * @param offsetAmount 可冲抵总量
     * @param dispenseAmount 请领数量
     */
    private void adjustPhamDispenseDetailAmountByOffsetAmount (Integer offsetAmount, List <InpPhamApplyDetailVO> offsetApplyDetails)
    {
        // 本次请领已经冲抵的药品数量
        Integer disAmount = 0;
        // // 如果冲抵的药品不能完全满足本次摆药需求
        // for (InpPhamDispenseDetailVO inpPhamDispenseDetailVO :
        // dispenseDetailList)
        // {
        // disAmount += inpPhamDispenseDetailVO.getDispenseAmount ();
        // // 如果冲抵的药品不能完全满足本次摆药需求
        // if (offsetAmount < disAmount)
        // {
        // inpPhamDispenseDetailVO.setActualDispenseAmount (disAmount -
        // offsetAmount);
        // inpPhamDispenseDetailVO.setDispenseAmount (disAmount - offsetAmount);
        // break;
        // }
        // inpPhamDispenseDetailVO.setActualDispenseAmount (0);
        // inpPhamDispenseDetailVO.setDispenseAmount (0);
        // }
        // 更新在途库冲抵数据

        // disAmount = 0;

        for (InpPhamApplyDetailVO inpPhamApplyDetailVO : offsetApplyDetails)
        {
            disAmount += inpPhamApplyDetailVO.getOffsetAmount ().intValue ();
            // 如果冲抵的药品不能完全满足本次摆药需求
            if (offsetAmount < disAmount)
            {
                inpPhamApplyDetailVO.setActualOffsetAmount (disAmount - offsetAmount);
                break;
            }
            inpPhamApplyDetailVO.setActualOffsetAmount (inpPhamApplyDetailVO.getOffsetAmount ().intValue ());
            if (offsetAmount == disAmount)
            {
                break;
            }
        }
    }

    /**
     * 根据摆药数量数量来更新冲抵请领明细中的药品数量以及其对应的摆药执行明细的摆药状态
     * 
     * @param offsetApplyDetailList
     * @param offsetAmount
     * @param dispenseAmount
     */
    private List <InpPhamDispenseDetail> adjustOffsetApplyDetailAmountByDispenseAmount (List <InpPhamApplyDetailVO> offsetApplyDetailList, double dispenseAmount,
                                                                                        List <InpPhamApplyDetailVO> aboutToOffsetApplyDetail)
    {
        double alreadyOffsetAmount = 0l;
        // 可冲抵数量更新0的请领执行明细
        List <InpPhamDispenseDetail> offsetedDispenseDetail;
        List <Long> applyDetailIdList = new ArrayList <Long> ();
        // 如果冲抵的药品不能完全满足本次摆药需求
        for (InpPhamApplyDetailVO inpPhamApplyDetailVO : offsetApplyDetailList)
        {
            alreadyOffsetAmount += inpPhamApplyDetailVO.getOffsetAmount ();
            // 如果已冲抵的药品数量大于摆药药品数量
            if (alreadyOffsetAmount > dispenseAmount)
            {
                inpPhamApplyDetailVO.setOffsetAmount (Math.round (alreadyOffsetAmount - dispenseAmount));
                aboutToOffsetApplyDetail.add (inpPhamApplyDetailVO);
                break;
            }
            // 更新
            inpPhamApplyDetailVO.setOffsetAmount (0l);
            inpPhamApplyDetailVO.setDispenseIndicator (InpDispenseIndicator.HasDrugReturn.getEnumCode ());
            aboutToOffsetApplyDetail.add (inpPhamApplyDetailVO);
            // 查询已冲抵的请领明细对应的摆药明细
            applyDetailIdList.add (inpPhamApplyDetailVO.getInpPhamApplyDetailId ());
        }
        // 更新本次可冲抵数量更新为0的请领明细对应摆药明细的摆药状态
        offsetedDispenseDetail = this.getInpPhamDispenseDetailBasicService ().findDispenseDetailListByApplyDetailIdList (applyDetailIdList);
        return offsetedDispenseDetail;
    }

    /** 日志记录器. */
    public static final Logger s_logger = LoggerFactory.getLogger (ApplyDetailOffsetPhamOp.class);

    /** 公司版权信息. */
    public static final String copyright = "Copyright 2014, TH Supcom Corporation";

    /** 提交路径. */
    public static final String SCC_BRANCH = "$URL$";

    /** 提交日期. */
    public static final String SCC_LAST_MODIFICATION_DATE = "$Date$";

    /** 最终修改人员. */
    public static final String SCC_LAST_MODIFIER_NAME = "$Author$";

    /** 最终版本号. */
    public static final String SCC_REVISION = "$Revision$";
}
